#include <my_header.h>

#define MYSQL_ERROR_CHECK(ret, error_flag, msg) \
    do { \
        if ((ret) == (error_flag)) { \
            fprintf(stderr, "%s: %s\n", msg, mysql_error(ret)); \
            exit(1); \
        } \
    } while (0)

#define MYSQL_QUERY_CHECK(ret, db, msg) \
    do { \
        if ((ret) != 0) { \
            fprintf(stderr, "%s error: %s\n", msg, mysql_error((db)->conn)); \
            exit(1); \
        } \
    } while (0)



typedef struct fileInfo_s{
    int id;
    char fileName[256];
    char userName[256];
    int parentId;
    int fileType;
    char path[1001];
    char hashValue[65];
    int isDeleted;
    int refCount;
}fileInfo_t;

typedef struct dbConnection_s{
    MYSQL* conn;
    char host[64];
    char user[32];
    char passWord[32];
    char dataBase[32];
    int port;
}dbConnection_t;

int dbInit(dbConnection_t* db,char *host,int port,char *userName,char* passWord,char *dataBase){
    db->conn=mysql_init(NULL);
    MYSQL_ERROR_CHECK(db->conn,NULL,"mysql_init");

    strcpy(db->host,host);
    strcpy(db->user,userName);
    strcpy(db->passWord,passWord);
    strcpy(db->dataBase,dataBase);
    db->port = port;
    return 0;
}

int dbConnect(dbConnection_t* db){
    MYSQL* ret = mysql_real_connect(db->conn,db->host,db->user,db->passWord,db->dataBase,db->port,NULL,0);
    MYSQL_ERROR_CHECK(ret,NULL,"mysql_real_connect");
    return 0;
}

MYSQL_RES* dbQuery(dbConnection_t* db,char* sql){
    printf("SQL:%s",sql);

    int ret = mysql_query(db->conn,sql);
    MYSQL_QUERY_CHECK(ret,db,"mysql_query");

    MYSQL_RES* result = mysql_store_result(db->conn);
    if(result==NULL&&mysql_field_count(db->conn)>0){
        fprintf(stderr,"mysql_store_result error:%s\n",mysql_error(db->conn));
        return NULL;
    }
    return result;
}

int dbExecute(dbConnection_t* db,char* sql){
    printf("SQL:%s\n",sql);
    int ret = mysql_query(db->conn,sql);
    MYSQL_QUERY_CHECK(ret,db,"mysql_query");
    return mysql_insert_id(db->conn);
}

int dbLastInsertId(dbConnection_t* db){
    return mysql_insert_id(db->conn);
}

int vfsFindByPath(dbConnection_t *db,char *userName,char* path,char* fileName,fileInfo_t* fileInfo){
    char sql[2048];
    snprintf(sql,sizeof(sql),
             "select id,fileName,userName,parentId,fileType,path,"
             "ifnull(hashValue,''),isDeleted,refCount "
             "from vfs "
             "where userName='%s' and path='%s' and fileName='%s' and isDeleted=0",
             userName, path, fileName);

    MYSQL_RES *result = dbQuery(db,sql);
    if(!result)return -1;

    MYSQL_ROW row = mysql_fetch_row(result);
    if(row){
        fileInfo->id = atoi(row[0]);
        strcpy(fileInfo->fileName,row[1]);
        strcpy(fileInfo->userName,row[2]);
        fileInfo->parentId = atoi(row[3]);
        fileInfo->fileType=atoi(row[4]);
        strcpy(fileInfo->path,row[5]);
        strcpy(fileInfo->hashValue,row[6]);
        fileInfo->isDeleted = atoi(row[7]);
        fileInfo->refCount = atoi(row[8]);
        mysql_free_result(result);
        return 0;
    }
    mysql_free_result(result);
    return 1;
}
//usage
/* file_info_t info; */
/* int found = vfs_find_by_path(db, "alice", "/docs", "readme.txt", &info); */
/* if (found == 0) { */
/*     // 查到文件了 */
/* } else { */
/*     // 没查到 */
/* } */

const char *numericFields[] = {"parentId", "fileType", "isDeleted", "refCount", NULL};
const char *stringFields[] = {"fileName", "hashValue", "path", NULL};

int isNumericField(char *field){
    for(int i=0;numericFields[i]!=NULL;i++){
        if(strcmp(field,numericFields[i])==0)return 1;
    }
    return 0;
}

int isStringField(char *field){
    for(int i=0;stringFields[i]!=NULL;i++){
        if(strcmp(field,stringFields[i])==0)return 1;
    }
    return 0;
}

int vfsUpdateField(dbConnection_t* db,char* field,char* value,char* userName,char* path,char* fileName){
    char sql[2048];
    if(isNumericField(field)){
        snprintf(sql,sizeof(sql),
                 "update vfs set %s=%s where userName='%s' and path='%s' and fileName='%s'",
                 field,value,userName,path,fileName);
    }else if(isStringField(field)){
        snprintf(sql,sizeof(sql),
                 "UPDATE vfs SET %s='%s' WHERE userName='%s' AND path='%s' AND fileName='%s'",
                 field, value, userName, path, fileName);
    }else{
        fprintf(stderr, "不允许修改字段：%s\n", field);
        return -1;
    }
    return dbExecute(db,sql);
}
//usage
/* vfs_update_field(db, "isDeleted", "1", "alice", "/docs", "foo.txt"); */
/* vfs_update_field(db, "hashValue", "newhashxxx", "alice", "/docs", "foo.txt"); */
/* vfs_update_field(db, "fileType", "1", "alice", "/docs", "foo.txt"); */

